package com.he.utils;

import com.baomidou.mybatisplus.core.conditions.AbstractWrapper;
import com.he.entity.Book;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadLocalRandom;
import java.util.function.*;
import java.util.stream.Stream;

public class FunctionUtil {

    /**
     * 普通函数
     *
     * @param a
     * @param b
     * @return
     */
    static int add(int a, int b) {
        return a + b;
    }

    /**
     * 函数化为对象
     */
//    interface Lambda{
//        int calculate(int a, int b);
//    }
//    static Lambda add = (a,b) -> a + b;
    public static void main(String[] args) throws IOException {
//        System.out.println(FunctionUtil.add(3, 4));
//        System.out.println(add.calculate(5, 5));

        /**
         * 函数对象的优点
         * 1、行为参数化      方法相同判断条件不同时，判断条件作为参数， 提高代码的通用性
         * 2、延迟执行
         *
         */
        //region    行为参数化
//        List<String> list1 = new ArrayList<>();
//        List<String> list2 = new ArrayList<>();
//        Collections.addAll(list1, "张一", "张二", "张三", "张三丰", "李四");
//        Collections.addAll(list2, "苹果","西瓜");
////        System.out.println(filter0(list, str -> str.length() == 3));
////        System.out.println(filter0(list, str -> str.startsWith("李")));
////        System.out.println(filter0(list, str -> str.equals("张三")));
//
//        Stream.of(list1,list2)
//                .forEach(System.out::println);
//        Type1 type1 = a -> (a & 1) == 0;
//        IntPredicate type11 = a -> (a & 1) == 0;
//
//        IntBinaryOperator type2 = (a, b) -> a + b;
//
//        Type2 book = () -> new Book();
//        Type3 bookList = () -> new ArrayList<Book>();
//
//        Type4<Book> bookType4 = () -> new Book();
//        Type4<List<Book>> bookListType4 = () -> new ArrayList<Book>();
//        Supplier<Book> bookType42 = () -> new Book();
//        Supplier<List<Book>> bookListType42 = () -> new ArrayList<Book>();
//
//        Type5<String, Book> obj1 = (Book b) -> b.getName();
//        Type5<Double, Book> obj2 = b -> b.getPrice();
//        Function<Book, Long> obj3 = b -> b.getId();
//endregion

        //region    函数接口使用
        //1 一个集合筛选出奇、偶数集合   一个参数，一个bool返回值  predicate
//        System.out.println("偶数集合："+filter(Arrays.asList(1, 2, 3, 4, 5, 6), number -> (number & 1) == 0));
//        System.out.println("奇数集合："+filter(Arrays.asList(1, 2, 3, 4, 5, 6), number -> (number & 1) == 1));

        //2 类型转换    一个参数，一个(目标类型)返回值    Function
//        System.out.println(map(Arrays.asList(1, 2, 3, 4, 5), number -> String.valueOf(number)));

        //3 输出、保存等  一个参数，没有返回值      consumer
//        consume(Arrays.asList(1,2,3,4),number-> System.out.println(number));
//        consume(Arrays.asList(1,2,3,4),System.out::println);

        //没有参数，一个返回值    supply
//        System.out.println(supply(10, () -> ThreadLocalRandom.current().nextInt(100)));


//        Stream.of(
//                        new Book("三国演艺", "军事"),
//                        new Book("红楼梦", "言情"),
//                        new Book("水浒传", "武侠"),
//                        new Book("西游记", "神话")
//                ).filter(FunctionUtil::nameIsThree)
//                .map(book -> book.getName() + " - " + book.getType())
////                .forEach(FunctionUtil::abc);
//                .forEach(System.out::println);

        //举例将一个数组中的数字按奇偶数分别输出
//        int[] arr = {1,2,3,4,5,6,7,8,9,10};
//        test(arr, o -> (o & 1) == 0);
//        System.out.println();
//        test(arr, o -> (o & 1) == 1);

        //endregion

        //region    闭包作用: 给所数对象提供参数以外的数据
        // 创建 10 个任务对象，并且每个任务对象给一个任务编号
        List<Runnable> list = new ArrayList<>();

        for (int i = 0; i < 10; i++) {
            int k = i + 1;  //闭包变量
            Runnable task = () -> System.out.println(Thread.currentThread()+"执行任务" + k);
            list.add(task);
        }
        ExecutorService service = Executors.newFixedThreadPool(10);
        for (Runnable runnable : list) {
            service.submit(runnable);
        }
        System.in.read();
        //endregion
    }

    static void test(int[] arr,Predicate<Integer> predicate){
        List<Integer> list1 = new ArrayList<>();
        List<Integer> list2 = new ArrayList<>();
        for (int i : arr) {
            if (predicate.test(i)){
                list1.add(i);
            }
        }
        list1.forEach(System.out::println);
    }
    static List<Integer> filter(List<Integer> list, Predicate<Integer> predicate) {
        List<Integer> newList = new ArrayList<>();
        for (Integer number : list) {
            if (predicate.test(number)) {
                newList.add(number);
            }
        }
        return newList;
    }

    static List<String> map(List<Integer> list, Function<Integer, String> func) {
        List<String> newList = new ArrayList<>();
        for (Integer number : list) {
            newList.add(func.apply(number));
        }
        return newList;
    }

    static void consume(List<Integer> list, Consumer<Integer> consumer) {
        for (Integer i : list) {
//            System.out.println(i);
            consumer.accept(i);
        }
    }

    static List<Integer> supply(int count, Supplier<Integer> supplier) {
        List<Integer> newList = new ArrayList<>();
        for (int i = 0; i < count; i++) {
            newList.add(supplier.get());
        }
        return newList;
    }

    static void abc(Book book) {
        System.out.println(book);
    }

    static boolean nameIsThree(Book book) {
        return book.getName().length() == 3;
    }

    @FunctionalInterface
    interface Type1 {
        boolean op(int a);
    }

    @FunctionalInterface
    interface Type2 {
        Book op();
    }

    @FunctionalInterface
    interface Type3 {
        List<Book> op();
    }

    @FunctionalInterface
    interface Type4<T> {
        T op();
    }

    @FunctionalInterface
    interface Type5<O, I> {
        O op(I input);
    }

    interface Lambda {
        boolean test(String str);
    }

    static List<String> filter0(List<String> list, Lambda lambda) {
        List<String> result = new ArrayList<>();
        for (String str : list) {
            if (lambda.test(str)) {
                result.add(str);
            }
        }
        return result;
    }

    //参数 -> 逻辑部分    str -> str.length() == 3
    static List<String> filter1(List<String> list) {
        List<String> result = new ArrayList<>();
        for (String str : list) {
            if (str.length() == 3) {
                result.add(str);
            }
        }
        return result;
    }

    //str -> str.startsWith("李")
    static List<String> filter2(List<String> list) {
        List<String> result = new ArrayList<>();
        for (String str : list) {
            if (str.startsWith("李")) {
                result.add(str);
            }
        }
        return result;
    }

}
